#include "CenterWidgetUI.h"
#include <QApplication>
#include <QFile>
#include <QDebug>
#include <QSpacerItem>
#include <QSizePolicy>
#include <QPushButton>
#include <QTimer>
// 构造函数：初始化 CenterWidgetUI 界面
CenterWidgetUI::CenterWidgetUI(QWidget *parent)
        : QWidget(parent)
{
    // ==================== 加载样式表 ====================
    QFile styleFile(":/qss/CenterWidgetStyle.qss"); // 打开 Qt 资源文件中的 QSS 样式
    if (styleFile.open(QFile::ReadOnly | QFile::Text)) { // 文件打开成功
        QString styleSheet = styleFile.readAll();        // 读取整个样式表内容
        // qApp->setStyleSheet(styleSheet);               // 应用样式表到整个应用程序
        this->setStyleSheet(styleSheet);     // 只影响当前的局部
        styleFile.close();                              // 关闭文件释放资源
    } else {
        qDebug() << "Failed to open style.qss!";      // 打印调试信息，提示文件打开失败
    }

    // ==================== 主布局（左右布局） ====================
    mainLayout = new QHBoxLayout(this);   // 创建水平布局，用于放置左侧和右侧面板
    mainLayout->setSpacing(15);           // 设置左右面板之间的间距为 15 像素
    mainLayout->setContentsMargins(15, 15, 15, 15); // 设置布局边距：左上右下均为 15 像素

    // ==================== 左侧面板 ====================
    QWidget *leftPanel = new QWidget(this); // 创建左侧面板控件
    leftPanel->setObjectName("leftPanel");  // 设置对象名，用于 QSS 样式匹配
    leftLayout = new QVBoxLayout(leftPanel); // 左侧面板使用垂直布局
    leftLayout->setSpacing(10);             // 设置控件间垂直间距为 10 像素
    leftLayout->setContentsMargins(15, 15, 15, 15); // 左侧面板内部边距

    // 图像显示标签
    inputImageLabel = new QLabel("图像预览区", this); // 初始化 QLabel 显示文本
    inputImageLabel->setAlignment(Qt::AlignCenter);  // 文本居中显示
    inputImageLabel->setMinimumSize(320, 240);       // 设置标签最小尺寸
    leftLayout->addWidget(inputImageLabel, 9);       // 添加到左侧布局，stretch=9，让图像显示占比大

    // 按钮区域
    QWidget *buttonArea = new QWidget(this);         // 创建按钮区域容器
    QHBoxLayout *btnLayout = new QHBoxLayout(buttonArea); // 按钮区域使用水平布局
    btnLayout->setContentsMargins(0, 0, 0, 0);      // 内边距设为 0
    btnLayout->setSpacing(15);                       // 按钮间距 15 像素

    // 创建按钮
    uploadBtn = new QPushButton("上传图片", this);   // 上传图片按钮
    cameraBtn = new QPushButton("打开摄像头", this); // 打开摄像头按钮

    // 设置对象名，用于 QSS 样式
    uploadBtn->setObjectName("uploadBtn");
    cameraBtn->setObjectName("cameraBtn");

    // 水平布局中添加按钮，并在两边添加拉伸，使按钮居中
    btnLayout->addStretch();         // 左侧拉伸
    btnLayout->addWidget(uploadBtn); // 添加上传按钮
    btnLayout->addWidget(cameraBtn); // 添加摄像头按钮
    btnLayout->addStretch();         // 右侧拉伸

    leftLayout->addWidget(buttonArea, 1); // 按钮区域加入左侧布局，stretch=1
    mainLayout->addWidget(leftPanel, 1);  // 左侧面板加入主布局，stretch=1

    // ==================== 右侧面板 ====================
    QWidget *rightPanel = new QWidget(this); // 创建右侧面板
    rightPanel->setObjectName("rightPanel"); // 设置对象名用于样式表
    rightLayout = new QVBoxLayout(rightPanel); // 右侧面板使用垂直布局
    rightLayout->setSpacing(10);               // 控件间垂直间距 10
    rightLayout->setContentsMargins(15, 15, 15, 15); // 内边距

    // 结果显示标签
    resultImageLabel = new QLabel("图像处理结果区", this); // 初始化 QLabel 显示文本
    resultImageLabel->setAlignment(Qt::AlignCenter);      // 文本居中显示
    resultImageLabel->setMinimumSize(320, 240);           // 最小尺寸
    rightLayout->addWidget(resultImageLabel, 9);         // stretch=9，让图像显示区域大

    // 按钮区域
    QWidget *toggleArea = new QWidget(this);             // 创建按钮区域容器
    QHBoxLayout *toggleLayout = new QHBoxLayout(toggleArea); // 水平布局
    toggleLayout->setContentsMargins(0, 0, 0, 0);       // 内边距 0
    toggleLayout->setSpacing(15);                        // 按钮间距 15

    toggleBtn = new QPushButton("展示结果", this);       // 创建按钮
    toggleBtn->setObjectName("toggleBtn");              // 设置对象名

    // 按钮居中
    toggleLayout->addStretch();    // 左拉伸
    toggleLayout->addWidget(toggleBtn); // 添加按钮
    toggleLayout->addStretch();    // 右拉伸

    rightLayout->addWidget(toggleArea, 1); // 按钮区域加入右侧布局，stretch=1
    mainLayout->addWidget(rightPanel, 1);  // 右侧面板加入主布局，stretch=1

    // 设置主布局到窗口
    setLayout(mainLayout);

    // ======================== 摄像头定时器 ========================
    timer = new QTimer(this);                          // 创建定时器对象
    connect(timer, &QTimer::timeout, this, &CenterWidgetUI::captureFrame); // 定时触发抓帧
}

// 当 CenterWidget 的大小发生改变时，会自动调用此函数
void CenterWidgetUI::resizeEvent(QResizeEvent *event)
{
    // 调用基类 QWidget 的 resizeEvent 方法，确保默认的行为（如子控件的大小调整）被正确执行
    QWidget::resizeEvent(event);
    // 如果原始输入图像不为空（已加载图像）
    if (!originalInputPixmap.isNull()) {
        // 将原始图像缩放到 inputImageLabel 的当前大小，并保持纵横比
        // 使用平滑变换（SmoothTransformation）提高缩放后的图像质量
        inputImageLabel->setPixmap(originalInputPixmap.scaled(
                inputImageLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
    }
    // 如果原始结果图像不为空，并且用于显示结果图像的标签是可见的
    if (!originalResultPixmap.isNull() && resultImageLabel->isVisible()) {
        // 将结果图像缩放到 resultImageLabel 的当前大小，并保持纵横比和平滑缩放
        resultImageLabel->setPixmap(originalResultPixmap.scaled(
                resultImageLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
    }
}

// 摄像头按钮点击槽函数
void CenterWidgetUI::onCameraButtonClicked()
{
    this->showingProcessedResult=false;// 设置标志，表示当前正在处理摄像头图片,因此需要设置图片的标识为false,表示当前是摄像头不是图片
    toggleCamera(); // 直接调用已有的 toggleCamera 函数
}

// 打开或关闭摄像头的槽函数
void CenterWidgetUI::toggleCamera()
{
    if (!cameraRunning) {// 如果摄像头本身是关闭的状态，因为本身是关闭的状态，因此此时的操作是为了打开摄像头
        // 打开摄像头0号设备
        if (!cap.open(0)) {
            inputImageLabel->setText("无法打开摄像头");
            return;
        }
        cameraRunning = true;// 设置状态表示当前的摄像头已经打开了
        timer->start(30);//  启动定时器，每30ms触发一次摄像头帧采集函数
        if (cameraBtn) cameraBtn->setText("关闭摄像头");// 修改按钮文本，原本是关闭的状态，那么按钮的文字就是显示打开摄像头，现在打开了，所以文字要变成关闭摄像头
        inputImageLabel->clear();// 清空图片
        resultImageLabel->setVisible(false);// 隐藏结果区域  默认结果区域是展示不显示的
        if (rightTimer){// 停止右侧定时器  因为不显示，所以要暂停右侧的记时操作
            qDebug() << "停止右侧定时器"<<rightTimer<<endl;
            rightTimer->stop();
        }
    } else {// 如果摄像头本身是打开的状态，因为本身是打开的状态，因此此时的操作是为了关闭摄像头
        timer->stop();// 停止定时器
        cap.release();// 释放摄像头
        cameraRunning = false;// 设置状态表示当前的摄像头已经关闭了
        if (cameraBtn) cameraBtn->setText("打开摄像头");// 修改按钮文本，原本是打开的状态，那么按钮的文字就是显示关闭摄像头，现在关闭了，所以文字要变成打开摄像头
        inputImageLabel->setText("摄像头已关闭");// 提示摄像头已关闭
        inputImageLabel->clear();// 清空图片
        if (rightTimer) {
            rightTimer->stop();// 停止右侧定时器
        }
        resultImageLabel->setVisible(false);// 隐藏结果区域
    }
}



/*
 * 本函数通过 cv::VideoCapture cap 采集摄像头画面。
使用 OpenCV 转换色彩空间以匹配 Qt 显示。
使用 QImage 和 QPixmap 将图像显示在 Qt 的界面控件上。
左边 inputImageLabel 始终显示当前帧。
如果右边 resultImageLabel 可见且摄像头正在运行（cameraRunning == true），右边也同步显示该帧。
 * */
// 从摄像头捕获一帧图像并显示在界面上的函数
void CenterWidgetUI::captureFrame()
{
    // 如果摄像头没有成功打开，则直接返回
    if (!cap.isOpened())
        return;
    // 创建一个空的 OpenCV 图像容器
    cv::Mat frame;
    // 从摄像头中读取一帧图像，存入 frame
    cap >> frame;
    // 如果捕获失败，frame 为空，则直接返回
    if (frame.empty())
        return;
    // 将图像从 BGR 格式转换为 RGB 格式（OpenCV 默认使用 BGR，Qt 使用 RGB）
    cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB);
    // 将 OpenCV 的 Mat 数据转换为 Qt 的 QImage，用于界面显示
    QImage img((const uchar*)frame.data,      // 图像数据指针
               frame.cols,                    // 图像宽度
               frame.rows,                    // 图像高度
               frame.step,                    // 每行的字节数（步长）
               QImage::Format_RGB888);        // 图像格式（每像素 3 字节，RGB）
    // 在左侧标签（inputImageLabel）上显示图像
    // 使用 scaled() 保持纵横比，并采用平滑缩放处理提高显示效果
    inputImageLabel->setPixmap(QPixmap::fromImage(img).scaled(
            inputImageLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
}


// 右侧摄像头画面更新函数（每帧调用）
void CenterWidgetUI::captureFrameRight()
{
    // 检查摄像头是否打开
    if (!cap.isOpened())
        return;
    // 读取一帧图像
    cv::Mat frame;
    cap >> frame;
    // 如果读取失败或为空，则退出
    if (frame.empty())
        return;
    // 转换色彩空间：OpenCV 默认 BGR，Qt 使用 RGB
    cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB);
    // 将 OpenCV Mat 转换为 QImage（用于通用图像处理接口）
    QImage inputImage((const uchar*)frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGB888);

    // 将处理后的图像显示在右侧标签中  先直接原图输出再说
    resultImageLabel->setPixmap(QPixmap::fromImage(inputImage).scaled(
            resultImageLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
}



// 槽函数：显示或隐藏右侧“图像处理结果”区域
/*
 * 函数的主要功能是在页面的右侧实现处理结果的实时展示操作
 * */
void CenterWidgetUI::toggleResultDisplay()
{
    // 需要首先判断当前是图片还是摄像头
    if (this->showingProcessedResult) {// 如果当前正在处理原始图片
        qDebug() << "当前的操作是处理单张图片的操作"<<endl;
        // 获取当前 resultImageLabel 是否可见
        bool visible = resultImageLabel->isVisible();
        qDebug() << "resultImageLabel isVisible:" << visible<<endl;
        // 设置 resultImageLabel 为与当前相反的可见状态（即切换显示或隐藏）
        resultImageLabel->setVisible(!visible);
        if (visible) {// 如果原本是可见的（即现在要隐藏），清空内容以释放资源
            resultImageLabel->clear();
        } else {
            //QString method = rightWidget->getCurrentMethod();
            //qDebug() << "用户当前选择的方法：" << method;
            //ProcessConfig config = RightWidget::getConfigForMethod(method);
            //QImage resultImage = doSimpleProcessing(originalInputPixmap.toImage(), config);
            processedResultPixmap = QPixmap::fromImage(originalInputPixmap.toImage());   // 转换为可展示的格式
            resultImageLabel->setPixmap(processedResultPixmap.scaled(
                    resultImageLabel->size(),                 // 缩放目标大小：当前标签大小
                    Qt::KeepAspectRatio,            // 保持原始宽高比例
                    Qt::SmoothTransformation));         // 使用平滑缩放算法
        }
    }
    else
    {// 视频  else部分处理的是图片的相关代码。
        qDebug() << "当前的操作处理的是视频"<<endl;// 获取当前 resultImageLabel 是否可见
        bool visible = resultImageLabel->isVisible();
        qDebug() << "resultImageLabel isVisible:" << visible<<endl;// 设置 resultImageLabel 为与当前相反的可见状态（即切换显示或隐藏）
        resultImageLabel->setVisible(!visible);
        if (visible) {// 如果原本是可见的（即现在要隐藏），清空内容以释放资源
            resultImageLabel->clear();
        } else {
            if (cameraRunning) {
                captureFrame();// 如果右侧定时器还没创建，则创建并连接定时器信号。因为因为摄像头什开着的，所以需要抓取侦进行事实的显示操作。
                if (!rightTimer) {
                    rightTimer = new QTimer(this);
                    connect(rightTimer, &QTimer::timeout, this, &CenterWidgetUI::captureFrameRight);
                }
                rightTimer->start(30);// 启动右侧定时器，约每 30 毫秒刷新一次右侧摄像头画面
            } else {
                if (!originalInputPixmap.isNull()) {// 将其保存为原始结果图像
                    originalResultPixmap = originalInputPixmap;// 缩放图像以适配右侧 resultImageLabel 的大小，并保持比例与平滑显示
                    resultImageLabel->setPixmap(originalResultPixmap.scaled(
                            resultImageLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
                }
            }
        }
    }
}